<template>
  <div class="cesium-drone-demo">
    <div class="controls">
      <button @click="startFlight" :disabled="isFlying">开始飞行</button>
      <button @click="stopFlight" :disabled="!isFlying">停止飞行</button>
      <button @click="resetFlight">重置轨迹</button>
      <div class="speed-control">
        <label>速度: {{ displaySpeed }} m/s</label>
        <input
          type="range"
          min="0.25"
          max="4"
          step="0.25"
          v-model.number="speedMultiplier"
          @input="applySpeed"
        />
      </div>
      <div class="flight-info">
        <span>飞行状态: {{ isFlying ? '飞行中' : '已停止' }}</span>
        <span class="current-position" :title="currentPosition">当前位置: {{ currentPosition }}</span>
      </div>
    </div>
    <div id="cesiumContainer" class="cesium-container"></div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from 'vue'
import * as Cesium from 'cesium'

// 响应式数据
const isFlying = ref(false)
const currentPosition = ref('未开始')
let viewer: Cesium.Viewer | null = null
let droneEntity: Cesium.Entity | null = null
let flightPathEntity: Cesium.Entity | null = null
let sampledPosition: Cesium.SampledPositionProperty | null = null
let startTime: Cesium.JulianDate | null = null
let stopTime: Cesium.JulianDate | null = null
let tickListener: ((clock: Cesium.Clock) => void) | null = null
const flightSpeedMetersPerSecond = 240

// 飞行速度倍速（通过时钟倍率实现动态速度调节）
const speedMultiplier = ref(2)
const displaySpeed = computed(() => Math.round(flightSpeedMetersPerSecond * speedMultiplier.value))
const applySpeed = () => {
  if (viewer) viewer.clock.multiplier = speedMultiplier.value
}

// 移除天地图注记（如需再次启用，请在此处添加 token 并叠加注记层）

// 无人机飞行路径点（环绕西安市区一圈）
// 参考范围约：东经 108.75 ~ 109.15，北纬 34.15 ~ 34.48
const flightPath = [
  { lng: 108.80, lat: 34.45, height: 300 },
  { lng: 108.88, lat: 34.47, height: 320 },
  { lng: 108.96, lat: 34.48, height: 320 },
  { lng: 109.04, lat: 34.47, height: 320 },
  { lng: 109.12, lat: 34.45, height: 300 },
  { lng: 109.15, lat: 34.38, height: 300 },
  { lng: 109.15, lat: 34.30, height: 320 },
  { lng: 109.13, lat: 34.22, height: 320 },
  { lng: 109.10, lat: 34.16, height: 300 },
  { lng: 109.00, lat: 34.13, height: 300 },
  { lng: 108.90, lat: 34.13, height: 300 },
  { lng: 108.82, lat: 34.16, height: 300 },
  { lng: 108.75, lat: 34.22, height: 320 },
  { lng: 108.73, lat: 34.30, height: 320 },
  { lng: 108.75, lat: 34.38, height: 300 },
  { lng: 108.80, lat: 34.45, height: 300 } // 回到起点，闭合一圈
]

// 初始化 Cesium
const initCesium = async () => {
  // 设置 Cesium 访问令牌（建议替换为你自己的）
  Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiNjc1ZDk0NC1iZTYxLTRiMzItYjQ3Ny1mYmY0MWQ3YjEzNWMiLCJpZCI6MzM0MDA5LCJpYXQiOjE3NTU3NjA1MTJ9.1WdYOpkKmSJfd5gXd8WtDj-VZNOajRRStAzcW9X20xs'

  // 创建 Cesium 视图
  viewer = new Cesium.Viewer('cesiumContainer', {
    homeButton: false,
    sceneModePicker: false,
    baseLayerPicker: false,
    navigationHelpButton: false,
    animation: false,
    timeline: false,
    fullscreenButton: false,
    geocoder: false,
    infoBox: false
  })

  // 设置卫星影像图层（使用高德卫星图 + 中文注记）
  viewer.imageryLayers.removeAll()
  try {
    // 高德卫星
    const gaodeSatellite = new Cesium.UrlTemplateImageryProvider({
      url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
      subdomains: ['1','2','3','4'],
      tilingScheme: new Cesium.WebMercatorTilingScheme(),
      minimumLevel: 0,
      maximumLevel: 18,
      credit: '高德地图卫星'
    })
    viewer.imageryLayers.addImageryProvider(gaodeSatellite)

    // 高德中文注记覆盖
    const gaodeLabels = new Cesium.UrlTemplateImageryProvider({
      url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=8&x={x}&y={y}&z={z}',
      subdomains: ['1','2','3','4'],
      tilingScheme: new Cesium.WebMercatorTilingScheme(),
      minimumLevel: 0,
      maximumLevel: 18,
      credit: '高德中文注记'
    })
    viewer.imageryLayers.addImageryProvider(gaodeLabels)

    // 中文注记已移除
    
    // 添加3D建筑图层
    const buildings = await Cesium.createOsmBuildingsAsync()
    viewer.scene.primitives.add(buildings)
    
    // 启用光照；关闭地形深度测试，避免近距离被地形遮挡导致消失
    viewer.scene.globe.enableLighting = true
    viewer.scene.globe.depthTestAgainstTerrain = false
    
  } catch (_) {
    // 如果加载失败，使用默认的影像
    console.log('使用默认影像图层')
  }

  // 可选：异步设置全球地形
  // try {
  //   const terrainProvider = await Cesium.createWorldTerrainAsync()
  //   viewer.terrainProvider = terrainProvider
  // } catch (_) {
  //   // 忽略地形加载失败，使用默认椭球
  // }

  // 不设置远景相机，后续直接贴近无人机

  // 添加路径折线（更显眼的发光描边）
  const positions = flightPath.map(p => Cesium.Cartesian3.fromDegrees(p.lng, p.lat, p.height))
  flightPathEntity = viewer.entities.add({
    name: '飞行路径',
    polyline: {
      positions,
      width: 6,
      material: new Cesium.PolylineOutlineMaterialProperty({
        color: Cesium.Color.CYAN,
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 2
      }),
      depthFailMaterial: new Cesium.PolylineOutlineMaterialProperty({
        color: Cesium.Color.CYAN.withAlpha(0.9),
        outlineColor: Cesium.Color.BLACK.withAlpha(0.9),
        outlineWidth: 2
      })
    }
  })

  // 基于时间的平滑飞行轨迹
  sampledPosition = new Cesium.SampledPositionProperty()
  sampledPosition.setInterpolationOptions({
    interpolationAlgorithm: Cesium.HermitePolynomialApproximation,
    interpolationDegree: 2
  })

  // 以恒定速度计算每段用时，生成时序采样
  startTime = Cesium.JulianDate.now()
  let segmentStart = Cesium.JulianDate.clone(startTime)
  let totalDurationSeconds = 0
  for (let i = 0; i < positions.length; i++) {
    if (i === 0) {
      sampledPosition.addSample(segmentStart, positions[i])
      continue
    }
    const distanceMeters = Cesium.Cartesian3.distance(positions[i - 1], positions[i])
    const segmentSeconds = distanceMeters / flightSpeedMetersPerSecond
    totalDurationSeconds += segmentSeconds
    segmentStart = Cesium.JulianDate.addSeconds(segmentStart, segmentSeconds, new Cesium.JulianDate())
    sampledPosition.addSample(segmentStart, positions[i])
  }
  stopTime = Cesium.JulianDate.addSeconds(startTime, totalDurationSeconds, new Cesium.JulianDate())

  // 配置时钟
  viewer.clock.startTime = startTime.clone()
  viewer.clock.stopTime = stopTime.clone()
  viewer.clock.currentTime = startTime.clone()
  viewer.clock.clockRange = Cesium.ClockRange.CLAMPED
  viewer.clock.multiplier = speedMultiplier.value
  viewer.clock.shouldAnimate = false

  // 添加路径点
  flightPath.forEach((point, index) => {
    viewer!.entities.add({
      name: `路径点 ${index + 1}`,
      position: Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height),
      point: { pixelSize: 8, color: Cesium.Color.RED, outlineColor: Cesium.Color.WHITE, outlineWidth: 2 },
      label: {
        text: `${index + 1}`,
        font: '12pt monospace',
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        outlineWidth: 2,
        verticalOrigin: Cesium.VerticalOrigin.CENTER
      }
    })
  })

  // 添加无人机模型（使用平滑轨迹与速度朝向）
  droneEntity = viewer.entities.add({
    name: '无人机',
    position: sampledPosition,
    orientation: new Cesium.VelocityOrientationProperty(sampledPosition),
    model: {
      uri: 'https://cdn.jsdelivr.net/gh/CesiumGS/cesium@1.120/Apps/SampleData/models/CesiumAir/Cesium_Air.glb',
      minimumPixelSize: 64,
      maximumScale: 20000,
      silhouetteColor: Cesium.Color.YELLOW,
      silhouetteSize: 2
    },
    label: {
      text: '无人机',
      font: 'bold 20pt sans-serif',
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      fillColor: Cesium.Color.YELLOW,
      outlineColor: Cesium.Color.BLACK,
      outlineWidth: 4,
      showBackground: true,
      backgroundColor: Cesium.Color.BLACK.withAlpha(0.6),
      backgroundPadding: new Cesium.Cartesian2(8, 6),
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      pixelOffset: new Cesium.Cartesian2(0, -25),
      scale: 1.2,
      disableDepthTestDistance: Number.POSITIVE_INFINITY
    }
  })

  // 初始贴近无人机：直接跳转到无人机当前位置，无过渡动画
  const initial = sampledPosition.getValue(viewer.clock.currentTime)
  if (initial) {
    viewer.scene.camera.flyTo({
      destination: initial,
      orientation: {
        heading: 0,
        pitch: Cesium.Math.toRadians(-25),
        roll: 0
      },
      duration: 0
    })
  }

  // 时钟回调：更新当前位置显示
  const onTick = (clock: Cesium.Clock) => {
    if (!sampledPosition) return
    const p = sampledPosition.getValue(clock.currentTime)
    if (!p) return
    const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(p)
    if (!carto) return
    const lng = Cesium.Math.toDegrees(carto.longitude)
    const lat = Cesium.Math.toDegrees(carto.latitude)
    const h = carto.height
    currentPosition.value = `${lng.toFixed(6)}, ${lat.toFixed(6)}, 高度: ${Math.round(h)}m`
  }
  viewer.clock.onTick.addEventListener(onTick)
  tickListener = onTick

  // 视角跟随无人机
  viewer.trackedEntity = droneEntity
}

// 开始飞行
const startFlight = () => {
  if (isFlying.value || !viewer || !droneEntity || !startTime) return
  viewer.clock.currentTime = startTime.clone()
  viewer.clock.shouldAnimate = true
  isFlying.value = true
}

// 停止飞行
const stopFlight = () => {
  if (!viewer) return
  viewer.clock.shouldAnimate = false
  isFlying.value = false
}

// 重置轨迹
const resetFlight = () => {
  stopFlight()
  if (viewer && startTime) {
    viewer.clock.currentTime = startTime.clone()
  }
  currentPosition.value = '未开始'
}

onMounted(async () => {
  await initCesium()
  // var custom = new Cesium.ArcGisMapServerImageryProvider({
  //   url: '//services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer'
  // });

  // const viewer = new Cesium.Viewer('cesiumContainer', {
  //   // sceneModePicker: false,
  //    baseLayerPicker: false,
  //    imageryProvider: custom,
  //    terrainProvider: Cesium.createWorldTerrainAsync({
  //     requestWaterMask: true,
  //     requestVertexNormals: true
  //    }),
  //   // navigationHelpButton: false,
  //   // animation: false,
  //   // timeline: false,
  //   // fullscreenButton: false,
  //   // geocoder: false,
  //   // infoBox: false
  // })
})

onUnmounted(() => {
  if (viewer && tickListener) viewer.clock.onTick.removeEventListener(tickListener)
  if (viewer) viewer.destroy()
})
</script>

<style scoped>
.cesium-drone-demo {
  display: flex;
  flex-direction: column;
  height: 100vh;
  background: #1a1a1a;
}

.controls {
  display: flex;
  gap: 10px;
  padding: 12px 15px;
  background: rgba(34, 34, 34, 0.85);
  border-bottom: 1px solid #444;
  align-items: center;
  flex-wrap: wrap;
  position: relative;
  z-index: 5;
}

.speed-control {
  display: flex;
  align-items: center;
  gap: 8px;
  color: #fff;
}

.controls button {
  padding: 8px 16px;
  background: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background 0.3s;
}

.controls button:hover:not(:disabled) { background: #45a049; }
.controls button:disabled { background: #666; cursor: not-allowed; }

.flight-info {
  display: flex;
  gap: 16px;
  color: #fff;
  font-size: 13px;
  /* margin-right: auto; */
}

.current-position {
  max-width: 48vw;
  white-space: normal;
  word-break: break-all;
}

.cesium-container { flex: 1; min-height: 0; }

@media (max-width: 768px) {
  .controls { flex-direction: column; align-items: stretch; gap: 8px; }
  .flight-info { margin-left: 0; justify-content: space-between; width: 100%; }
}
</style> 